using System.Collections.Generic;
using System.Text.Json.Nodes;
using Engine;
using Engine.Graphics;
using Game;

namespace RuthlessConquest {
    public class GameMenuDialog : Dialog {
        public RectangleWidget Planet1Widget;
        public RectangleWidget Planet2Widget;
        public RectangleWidget ShipsWidget;
        public LabelWidget TipWidget;
        public ListPanelWidget SpectatorsWidget;
        public ButtonWidget ResumeWidget;
        public ButtonWidget DisconnectWidget;
        public ButtonWidget StartWidget;
        public CheckboxWidget NoMoreWidget;
        public ContainerWidget ButtonsContainer1;
        public ContainerWidget ButtonsContainer2;
        public GameScreen GameScreen;

        public static int TipIndex;
        public static Dictionary<int, double> TipLastSeenTimes = [];
        public static int TipCount;
        public const string fName = "RCGameMenuDialog";

        public GameMenuDialog(GameScreen gameScreen, bool initialInstructions) {
            GameScreen = gameScreen;
            Size = new Vector2(720f, 420f);
            ClampToBounds = true;
            HorizontalAlignment = WidgetAlignment.Center;
            VerticalAlignment = WidgetAlignment.Center;
            Widget[] rootChildren = [
                new RectangleWidget { FillColor = Colors.Back, OutlineColor = Colors.ForeDim, OutlineThickness = 2f }, new InterlaceWidget(), null
            ];
            StackPanelWidget rootPanel = new() {
                Direction = LayoutDirection.Vertical, HorizontalAlignment = WidgetAlignment.Center, Margin = new Vector2(0f, 10f)
            };
            StackPanelWidget mainPanel = new() { HorizontalAlignment = WidgetAlignment.Center };
            CanvasWidget leftPanelContainer = new() { Size = new Vector2(-1f, float.PositiveInfinity) };
            StackPanelWidget leftPanel = new() {
                Direction = LayoutDirection.Vertical,
                Margin = new Vector2(10f, 0f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(fName, "1"), Margin = new Vector2(0f, 5f), HorizontalAlignment = WidgetAlignment.Center
                    },
                    new CanvasWidget { Size = new Vector2(float.PositiveInfinity, float.PositiveInfinity) },
                    new LabelWidget {
                        HorizontalAlignment = WidgetAlignment.Center,
                        FontScale = 0.75f,
                        Color = Colors.ForeDim,
                        TextAnchor = TextAnchor.HorizontalCenter,
                        WordWrap = true,
                        Margin = new Vector2(0f, 4f),
                        Text = LanguageControl.Get(fName, "2")
                    }
                }
            };
            StackPanelWidget diagramPanel = new() { Margin = new Vector2(0f, 8f), HorizontalAlignment = WidgetAlignment.Center };
            CanvasWidget planet1Canvas = new() { Size = new Vector2(120f, 100f) };
            Planet1Widget = new RectangleWidget {
                HorizontalAlignment = WidgetAlignment.Center,
                VerticalAlignment = WidgetAlignment.Near,
                Size = new Vector2(76f, 76f),
                Texcoord1 = new Vector2(0.1f, 0.1f),
                Texcoord2 = new Vector2(0.9f, 0.9f),
                FillColor = Color.White,
                OutlineColor = Color.Transparent,
                Subtexture = new Subtexture(Textures.Planet, Vector2.Zero, Vector2.One)
            };
            planet1Canvas.Children.Add(Planet1Widget);
            planet1Canvas.Children.Add(
                new LabelWidget {
                    HorizontalAlignment = WidgetAlignment.Center,
                    VerticalAlignment = WidgetAlignment.Far,
                    FontScale = 0.75f,
                    Color = Colors.HighDim,
                    TextAnchor = TextAnchor.HorizontalCenter,
                    Margin = new Vector2(0f, 4f),
                    Text = LanguageControl.Get(fName, "3")
                }
            );
            diagramPanel.Children.Add(planet1Canvas);
            CanvasWidget shipsCanvas = new() { Size = new Vector2(120f, 100f) };
            ShipsWidget = new RectangleWidget {
                HorizontalAlignment = WidgetAlignment.Center,
                VerticalAlignment = WidgetAlignment.Near,
                Size = new Vector2(76f, 76f),
                FillColor = Color.White,
                OutlineColor = Color.Transparent,
                Subtexture = new Subtexture(Textures.Gui.Ships, Vector2.Zero, Vector2.One)
            };
            shipsCanvas.Children.Add(ShipsWidget);
            diagramPanel.Children.Add(shipsCanvas);
            CanvasWidget planet2Canvas = new() { Size = new Vector2(120f, 100f) };
            Planet2Widget = new RectangleWidget {
                HorizontalAlignment = WidgetAlignment.Center,
                VerticalAlignment = WidgetAlignment.Near,
                Size = new Vector2(76f, 76f),
                Texcoord1 = new Vector2(0.1f, 0.1f),
                Texcoord2 = new Vector2(0.9f, 0.9f),
                FillColor = Color.White,
                OutlineColor = Color.Transparent,
                Subtexture = new Subtexture(Textures.Planet2, Vector2.Zero, Vector2.One)
            };
            planet2Canvas.Children.Add(Planet2Widget);
            planet2Canvas.Children.Add(
                new LabelWidget {
                    HorizontalAlignment = WidgetAlignment.Center,
                    VerticalAlignment = WidgetAlignment.Far,
                    FontScale = 0.75f,
                    Color = Colors.HighDim,
                    TextAnchor = TextAnchor.HorizontalCenter,
                    Margin = new Vector2(0f, 4f),
                    Text = LanguageControl.Get(fName, "4")
                }
            );
            diagramPanel.Children.Add(planet2Canvas);
            leftPanel.Children.Add(diagramPanel);
            leftPanel.Children.Add(
                new LabelWidget {
                    HorizontalAlignment = WidgetAlignment.Center,
                    FontScale = 0.75f,
                    Color = Colors.ForeDim,
                    TextAnchor = TextAnchor.HorizontalCenter,
                    WordWrap = true,
                    Margin = new Vector2(0f, 4f),
                    Text = LanguageControl.Get(fName, "5")
                }
            );
            TipWidget = new LabelWidget {
                HorizontalAlignment = WidgetAlignment.Center,
                FontScale = 0.75f,
                Color = Colors.HighDim,
                TextAnchor = TextAnchor.HorizontalCenter,
                WordWrap = true,
                Margin = new Vector2(0f, 12f)
            };
            leftPanel.Children.Add(TipWidget);
            leftPanel.Children.Add(new CanvasWidget { Size = new Vector2(0f, float.PositiveInfinity) });
            leftPanelContainer.Children.Add(leftPanel);
            mainPanel.Children.Add(leftPanelContainer);
            if (!initialInstructions) {
                PlayersModule playersModule = GameScreen.Client.Game.PlayersModule;
                ReadOnlyList<Player> spectators = playersModule.Spectators;
                if (spectators.Count > 0) {
                    Size = new Vector2(880f, 420f);
                    leftPanelContainer.Size = new Vector2(520f, float.PositiveInfinity);
                    CanvasWidget rightPanelContainer = new() { Size = new Vector2(340f, float.PositiveInfinity) };
                    StackPanelWidget rightPanel = new() {
                        Direction = LayoutDirection.Vertical,
                        Margin = new Vector2(10f, 0f),
                        Children = {
                            new LabelWidget {
                                HorizontalAlignment = WidgetAlignment.Center, Margin = new Vector2(0f, 5f), Text = LanguageControl.Get(fName, "14")
                            }
                        }
                    };
                    CanvasWidget spectatorsWidgetContainer = new() {
                        Size = new Vector2(320f, float.PositiveInfinity), Margin = new Vector2(0f, 10f)
                    };
                    SpectatorsWidget = new ListPanelWidget { Direction = LayoutDirection.Vertical, ItemSize = 40f };
                    SpectatorsWidget.ItemWidgetFactory = item => {
                        if (item is not Player player) {
                            return null;
                        }
                        StackPanelWidget rootPanel1 = new() { VerticalAlignment = WidgetAlignment.Center };
                        RectangleWidget platformRectangle = new() {
                            Size = new Vector2(20f, 20f),
                            OutlineColor = Color.Transparent,
                            FillColor = Color.White,
                            Margin = new Vector2(5f, 0f),
                            VerticalAlignment = WidgetAlignment.Center,
                            Subtexture = Player.GetPlatformTexture(player.Platform)
                        };
                        rootPanel1.Children.Add(platformRectangle);
                        LabelWidget nameLabel = new() {
                            FontScale = 0.75f,
                            Margin = new Vector2(3f, 0f),
                            VerticalAlignment = WidgetAlignment.Center,
                            Color = Colors.ForeDim,
                            Text = PlayerLabelWidget.IsPlayerColocated(player) ? player.Name + "*" : player.Name,
                            Ellipsis = true
                        };
                        rootPanel1.Children.Add(nameLabel);
                        if (SettingsManager.ShowFlags) {
                            if (playersModule.PlayerLocations.TryGetValue(player.Guid, out string location)
                                && location != null) {
                                Texture2D flagTexture = IpLocationManager.GetFlagTexture(location);
                                if (flagTexture != null) {
                                    RectangleWidget flagRectangle = new() {
                                        Size = new Vector2(36f, 18f),
                                        OutlineColor = Color.Transparent,
                                        FillColor = Color.White,
                                        Margin = new Vector2(8f, 0f),
                                        VerticalAlignment = WidgetAlignment.Center,
                                        Subtexture = flagTexture
                                    };
                                    rootPanel1.Children.Add(flagRectangle);
                                }
                            }
                        }
                        return rootPanel1;
                    };
                    foreach (Player spectator in spectators) {
                        SpectatorsWidget.AddItem(spectator);
                    }
                    SpectatorsWidget.ScrollPosition = 0f;
                    spectatorsWidgetContainer.Children.Add(SpectatorsWidget);
                    rightPanel.Children.Add(spectatorsWidgetContainer);
                    rightPanelContainer.Children.Add(rightPanel);
                    mainPanel.Children.Add(rightPanelContainer);
                }
            }
            rootPanel.Children.Add(mainPanel);
            rootPanel.Children.Add(new CanvasWidget { Size = new Vector2(0f, 10f) });
            ButtonsContainer1 = new StackPanelWidget {
                Direction = LayoutDirection.Horizontal, Children = { new CanvasWidget { Size = new Vector2(float.PositiveInfinity, 0f) } }
            };
            StartWidget = new BevelledButtonWidget {
                Text = LanguageControl.Get(fName, "6"), Size = new Vector2(200f, 60f), Sound = "RCSounds/Click2"
            };
            ButtonsContainer1.Children.Add(StartWidget);
            ButtonsContainer1.Children.Add(new CanvasWidget { Size = new Vector2(float.PositiveInfinity, 0f) });
            NoMoreWidget = new CheckboxWidget { Text = LanguageControl.Get(fName, "7"), VerticalAlignment = WidgetAlignment.Center };
            ButtonsContainer1.Children.Add(NoMoreWidget);
            ButtonsContainer1.Children.Add(new CanvasWidget { Size = new Vector2(float.PositiveInfinity, 0f) });
            rootPanel.Children.Add(ButtonsContainer1);
            ButtonsContainer2 = new StackPanelWidget {
                Direction = LayoutDirection.Horizontal, Children = { new CanvasWidget { Size = new Vector2(float.PositiveInfinity, 0f) } }
            };
            ResumeWidget = new BevelledButtonWidget {
                Text = LanguageControl.Get(fName, "8"), Size = new Vector2(250f, 60f), Sound = "RCSounds/Click2"
            };
            ButtonsContainer2.Children.Add(ResumeWidget);
            ButtonsContainer2.Children.Add(new CanvasWidget { Size = new Vector2(float.PositiveInfinity, 0f) });
            DisconnectWidget = new BevelledButtonWidget {
                Text = LanguageControl.Get(fName, "9"), Size = new Vector2(250f, 60f), Sound = "RCSounds/Click2"
            };
            ButtonsContainer2.Children.Add(DisconnectWidget);
            ButtonsContainer2.Children.Add(new CanvasWidget { Size = new Vector2(float.PositiveInfinity, 0f) });
            rootPanel.Children.Add(ButtonsContainer2);
            rootChildren[2] = rootPanel;
            Children.Add(rootChildren);
            SettingsManager.InstructionsShown = true;
            ButtonsContainer1.IsVisible = initialInstructions;
            ButtonsContainer2.IsVisible = !initialInstructions;
            HumanPlayer controllingPlayer = GameScreen.Client.Game.PlayersModule.ControllingPlayer;
            Faction faction = controllingPlayer != null && controllingPlayer.Faction != Faction.None
                ? controllingPlayer.Faction
                : GameScreen.Client.Game.CreationParameters.CreatingPlayerFaction;
            Planet1Widget.FillColor = Planet.GetColor(faction);
            ShipsWidget.FillColor = Ship.GetColor(faction);
            Planet2Widget.FillColor = Planet.GetColor((Faction)((int)(faction + new Random().Int(4) + 1) % 6));
            JsonArray tipsArray = LanguageControl.jsonNode["RCTips"]?.AsArray();
            if (tipsArray == null) {
                return;
            }
            TipCount = tipsArray.Count;
            int num = TipIndex % TipCount;
            if (TipLastSeenTimes.TryGetValue(num, out double value)
                && value > 0.0
                && Time.FrameStartTime - value < TipCount * 8) {
                TipWidget.Text = LanguageControl.Get(fName, "10");
                TipLastSeenTimes.Clear();
            }
            else {
                TipWidget.Text = tipsArray[num]?.ToString() ?? string.Empty;
                TipLastSeenTimes[num] = Time.FrameStartTime;
                TipIndex++;
            }
        }

        public override void Update() {
            if (GameScreen.Server != null
                && GameScreen.Server.IsUsingInProcessTransmitter) {
                GameScreen.Server.IsPaused = true;
                GameScreen.Client.IsPaused = true;
            }
            HumanPlayer controllingPlayer = GameScreen.Client.Game.PlayersModule.ControllingPlayer;
            if (StartWidget.IsClicked) {
                Dismiss(false);
            }
            if (NoMoreWidget.IsClicked) {
                SettingsManager.DontShowInstructions = NoMoreWidget.IsChecked;
            }
            if (Input.Back
                || ResumeWidget.IsClicked
                || (Input.Tap.HasValue && !HitTest(Input.Tap.Value))) {
                Dismiss(false);
            }
            if (DisconnectWidget.IsClicked) {
                if (GameScreen.Server != null) {
                    if (GameScreen.Server.IsUsingInProcessTransmitter) {
                        Dismiss(true);
                    }
                    else {
                        DialogsManager.ShowDialog(
                            this,
                            new MessageDialog(
                                LanguageControl.Warning,
                                LanguageControl.Get(fName, "11"),
                                LanguageControl.Yes,
                                LanguageControl.No,
                                delegate(MessageDialogButton b) {
                                    if (b == MessageDialogButton.Button1) {
                                        Dismiss(true);
                                    }
                                }
                            )
                        );
                    }
                }
                else if (controllingPlayer != null
                    && controllingPlayer.Faction != Faction.None
                    && controllingPlayer.Status == FactionStatus.Undecided) {
                    DialogsManager.ShowDialog(
                        this,
                        new MessageDialog(
                            LanguageControl.Warning,
                            LanguageControl.Get(fName, "12"),
                            LanguageControl.Yes,
                            LanguageControl.No,
                            delegate(MessageDialogButton b) {
                                if (b == MessageDialogButton.Button1) {
                                    Dismiss(true);
                                }
                            }
                        )
                    );
                }
                else {
                    DialogsManager.ShowDialog(
                        this,
                        new MessageDialog(
                            LanguageControl.Warning,
                            LanguageControl.Get(fName, "13"),
                            LanguageControl.Yes,
                            LanguageControl.No,
                            delegate(MessageDialogButton b) {
                                if (b == MessageDialogButton.Button1) {
                                    Dismiss(true);
                                }
                            }
                        )
                    );
                }
            }
            NoMoreWidget.IsChecked = SettingsManager.DontShowInstructions;
        }

        public void Dismiss(bool disconnect) {
            IsUpdateEnabled = false;
            DialogsManager.HideDialog(this);
            if (GameScreen.Server != null
                && GameScreen.Server.IsUsingInProcessTransmitter) {
                GameScreen.Client.IsPaused = false;
                GameScreen.Server.IsPaused = false;
            }
            if (disconnect) {
                GameScreen.Disconnect();
            }
        }
    }
}